#!/usr/bin/python

import socket
import messages
import math
import struct
import time
import packet_queue

UDP_IP = "0.0.0.0"
UDP_PORT = 5005
IN_BUFFER_SIZE = 2048

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

#sock_out = socket.socket(socket.AF_INET, # Internet
#                     socket.SOCK_DGRAM) # UDP

class DataCache:
  def __init__(self,data,packet_size):
    self.packet_size = packet_size
    self.num_packets = int(math.ceil(float(len(data))/float(packet_size)))
    print self.num_packets
    self.data = {}
    for i in range(self.num_packets):
      self.data[i] = data[(i)*packet_size:(i+1)*packet_size]
    self.queue = packet_queue.Queue(self.num_packets,1)
   
  def get_next_packet(self):
    if not self.queue.empty():
      packet_id = self.queue.next_id()
      self.queue[packet_id] = 0
      return (packet_id,self.data[packet_id])
    return (None,None)

    

while True:
    sock.settimeout(None)
    data, addr = sock.recvfrom(IN_BUFFER_SIZE) 
    file_message = messages.get_message(data)
    print "received message:", file_message
    
    if isinstance(file_message,messages.GetFileMessage):
      print 'Got file request: ',file_message.filename
      timeout = float(file_message.packet_size)/float(file_message.rate)
      print 'timeout: ', timeout
      sock.settimeout(timeout)
      try:
        with open(file_message.filename,'r') as f:
          data_cache = DataCache(f.read(),file_message.packet_size)
          print 'length: ', len(data_cache.data)
         
          timeout_count = 0
          # 10 second timeout by loop counting
          timeout_count_max = math.ceil(10.0/float(timeout))
          while not data_cache.queue.empty() or timeout_count < timeout_count_max:
            try:
              data2, addr2 = sock.recvfrom(IN_BUFFER_SIZE)
              packets_message = messages.get_message(data2)
              if isinstance(packets_message,messages.GetPacketsMessage):
                print 'received packets message: ', packets_message
                data_cache.queue = packets_message.queue
                print data_cache.queue
            except (KeyboardInterrupt, SystemExit):
              raise
            except Exception as e:
              (packet_id,data) = data_cache.get_next_packet()
              if packet_id is not None:
                timeout_count = 0
                message = messages.SendPacketMessage(data_cache.num_packets,packet_id,data)
                print addr, message
                sock.sendto(message.pack(), addr)
              else:
                timeout_count += 1
                #print "timeout_count: ", timeout_count, "max: ", timeout_count_max

      except IOError:
        print 'No file: ', file_message.filename
        
        
        
      
      